package com.outfood.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.util.concurrent.MoreExecutors;
import com.outfood.common.common.Result;
import com.outfood.common.evaluate.Ex;
import com.outfood.service.IStoreService;
import com.outfood.service.SeleniumService;
import com.outfood.utils.BingTopUtil;
import com.ruoyi.common.exception.BusinessException;
import com.rys.common.json.JSONObject;
import com.rys.common.utils.StringUtils;
import com.tps.open.oss.UploadService;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ThreadUtils;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import org.openqa.selenium.*;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.BindException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author huisonglin
 * @Description
 * @PackageName outfood-platform
 * @Package com.outfood.service.impl
 * @Date 2024-04-03 13:38
 * @Version 1.0
 */
@Log4j2
public class SeleniumServiceImpl implements SeleniumService {


    private WebDriver webDriver;




    public SeleniumServiceImpl(){
        try {
            createWebDriver();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public WebDriver createWebDriver(){
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.addArguments("--disable-blink-features=AutomationControlled");
        chromeOptions.setExperimentalOption("useAutomationExtension",false);
        chromeOptions.setExperimentalOption("excludeSwitches",new String[]{"enable-automation"});
        WebDriver driver = new ChromeDriver(chromeOptions);
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        this.webDriver = driver;
        return driver;
    }

    public WebDriver createLiunxWebDriver(String hubUrl) throws IOException {
        ChromeOptions chromeOptions = new ChromeOptions();
        /**
         *             chrome_options = Options()
         *             chrome_options.add_argument("--headless")  # 无界面模式
         *             chrome_options.add_argument("--disable-gpu")  # 无界面模式
         *             chrome_options.add_argument("--window-size=1920,1080")
         *             chrome_options.add_argument('--no-sandbox')
         *             chrome_options.add_argument('--ignore-certificate-errors')
         *             chrome_options.add_argument("--disable-extensions")
         *             chrome_options.add_argument("--disable-software-rasterizer")
         *             chrome_options.add_argument('--allow-running-insecure-content')
         *             #chrome_options.add_argument("blink-settings=imagesEnabled=false")
         *             chrome_options.add_experimental_option("excludeSwitches",['enable-automation'])
         */
        chromeOptions.addArguments("--no-sandbox");
        chromeOptions.addArguments("--ignore-certificate-errors");
        chromeOptions.addArguments("--disable-extensions");
        chromeOptions.addArguments("--disable-software-rasterizer");
        chromeOptions.addArguments("--allow-running-insecure-content");
        chromeOptions.addArguments("--disable-blink-features=AutomationControlled");
        chromeOptions.addArguments("--disable-gpu");
        chromeOptions.setExperimentalOption("useAutomationExtension",false);
        chromeOptions.setExperimentalOption("excludeSwitches",new String[]{"enable-automation"});
        DesiredCapabilities capbilities = DesiredCapabilities.chrome();
        URL url = new URL(hubUrl);
        RemoteWebDriver driver = new RemoteWebDriver(url,capbilities);
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);
        this.webDriver = driver;
        return driver;
    }

//    public static void main(String[] args) throws IOException {
//        System.setProperty("webdriver.chrome.driver","C:\\Users\\hsl\\.cache\\selenium\\chromedriver\\win64\\123.0.6312.86\\chromedriver.exe");
//        SeleniumServiceImpl seleniumServiceTest = null;
//
//            seleniumServiceTest = new SeleniumServiceImpl();
////            seleniumServiceTest.getQrCode(1L);
//            seleniumServiceTest.elemePhoneLogin("15856902499");
//
//    }

    public void elemePhoneLogin(String moible,IStoreService storeService,Long userId,RedisTemplate redisTemplate){
        try {
            webDriver.get("https://melody.shop.ele.me/login");
            //选择手机号登录
            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[1]/div[1]/div[1]/div/div[2]")).click();
            //点击阅读条款
            webDriver.findElement(By.xpath("//*[@id=\"mobile_login\"]/div[2]/div/div/div/div/div[1]/label/span[1]/input")).click();

            //收入手机号
            webDriver.findElement(By.xpath("//*[@id=\"mobile_login_mobile\"]")).sendKeys(moible);
            //点击获取验证码
            webDriver.findElement(By.xpath("//*[@id=\"mobile_login\"]/div[2]/div/div/div/button")).click();

            getalertphoneError();
            if(iselemeSendCodeSuccess()){
                log.info("等待输入验证码");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String code = getCode(userId+"",redisTemplate);
                            char[] charArray = code.toCharArray();
                            String[] codes = {charArray[0]+"",charArray[1]+"",charArray[2]+"",charArray[3]+"",charArray[4]+"",charArray[5]+""};
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[1]")).sendKeys(codes[0]);
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[2]")).sendKeys(codes[1]);
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[3]")).sendKeys(codes[2]);
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[4]")).sendKeys(codes[3]);
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[5]")).sendKeys(codes[4]);
                            webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[6]")).sendKeys(codes[5]);
                            isAlertError();
                            if(elemeIspasswordLoingSuccess()){
                                log.info("验证码登录成功了");
                                log.info("登录成功");
                                new WebDriverWait(webDriver, 3).until((WebDriver driver) -> {
                                    JavascriptExecutor js = (JavascriptExecutor) driver;
                                    Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
                                    System.out.println("页面是否已经加载完成"+result);
                                    return result;
                                });
                                log.info("开始获取strage信息");
                                //获取cookie
                                JavascriptExecutor js = (JavascriptExecutor) webDriver;
                                String ksid = (String) js.executeScript("return window.localStorage.getItem('ksid')");
                                String shopId = (String) js.executeScript("return window.localStorage.getItem('shopId')");
                                String shopName = (String) js.executeScript("return window.localStorage.getItem('shopName')");
                                log.info("{}{}{}",ksid,shopId,shopName);
                                storeService.loginByQrCode(ksid,shopId,shopName,userId,moible);
                                redisTemplate.opsForValue().set(CODEINFO+userId,new CodeLoginResult("0","验证码登录成功"));

                            }else{
                                redisTemplate.opsForValue().set(CODEINFO+userId,new CodeLoginResult("500","系统开小差了"));
                            }
                        } catch (Exception e) {
                            CodeLoginResult codeLoginResult = new CodeLoginResult("500", e.getMessage());
                            redisTemplate.opsForValue().set(CODEINFO+userId,codeLoginResult);
                            throw new RuntimeException(e);
                        }finally {
                            webDriver.quit();
                            redisTemplate.delete(userId + "code");
                        }
                    }
                }).start();
            }else{
                throw new BusinessException("系统开小差了");
            }
        } catch (Exception e) {
            webDriver.quit();
            log.error(e);
            throw e;
        }
    }

    public void getalertphoneError(){
        log.info("开始判断有没有店铺等其他信息");
        try {
            try {
                WebElement untile = new WebDriverWait(this.webDriver, 2).until(
                        ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[2]/div/div/div/div"))
                );
                throw new BusinessException(untile.getText());
            } catch (BusinessException e) {
                throw e;
            }catch (Exception e){
                log.error(e);
            }
            WebElement emnt = new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/button[2]"))
            );
            WebElement until = new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/p"))
            );
            throw new BusinessException(until.getText());
        } catch (BusinessException e) {
            throw e;
        } catch ( Exception e){
            log.error(e);
        }
    }

    public Boolean iselemeSendCodeSuccess(){
        try {
            WebElement until = new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div[1]/div/div/input[1]"))
            );
            log.info("验证码发送成功了");
            return true;
        } catch (TimeoutException e) {
            return false;
        } catch (Exception e){
            throw  e;
        }


    }
    public static String CODEINFO="codeInfo";

    @Data
    public static class CodeLoginResult{
        private String code;

        private String message;

        public CodeLoginResult(){

        }
        public CodeLoginResult(String code,String message){
            this.code = code;
            this.message = message;
        }
    }

    public CodeLoginResult elemePassword(String username,String password,Long userId, IStoreService storeService, RedisTemplate redisTemplate){

        try {
            this.webDriver.get("https://melody.shop.ele.me/login");
            //点击我已阅读条款
            this.webDriver.findElement(By.xpath("//*[@id='username_login']/div[3]/div/div/div/div/div[1]/label/span[1]/input")).click();
            //输入账号
            this.webDriver.findElement(By.xpath("//*[@id='username_login_username']")).sendKeys(username);
            //输入密码
            this.webDriver.findElement(By.xpath("//*[@id='username_login_password']")).sendKeys(password);
            //点击登录
            this.webDriver.findElement(By.xpath("//*[@id='username_login']/div[3]/div/div/div/button")).click();
            //开始判断是否出出现了弹框
            isAlertError();
            toSlider(this.webDriver);

            if(elemeIspasswordLoingSuccess()){
                log.info("登录成功");
                new WebDriverWait(webDriver, 5).until((WebDriver driver) -> {
                    JavascriptExecutor js = (JavascriptExecutor) driver;
                    Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
                    System.out.println("页面是否已经加载完成"+result);
                    return result;
                });
                log.info("开始获取strage信息");
                //获取cookie
                JavascriptExecutor js = (JavascriptExecutor) webDriver;
                String ksid = (String) js.executeScript("return window.localStorage.getItem('ksid')");
                String shopId = (String) js.executeScript("return window.localStorage.getItem('shopId')");
                String shopName = (String) js.executeScript("return window.localStorage.getItem('shopName')");
                log.info("{}{}{}",ksid,shopId,shopName);
                storeService.loginByQrCode(ksid,shopId,shopName,userId,username,password);
                try {
                    webDriver.quit();
                } catch (Exception e) {
                    log.error(e);
                }
                return new CodeLoginResult("0","操作成功");
            }else{
                log.info("登录失败可能需要验证码");
                if("弹出验证码了".equals(isCheckVateCode())){
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String code = getCode(userId+"",redisTemplate);
                                log.info("获取到验证码验证码为{}",code);
                                webDriver.findElement(By.xpath("//*[@id='ivs_container']/div/div[2]/div/div[2]/div[2]/div/div/div[1]/div[1]/span/input")).sendKeys(code);
                                webDriver.findElement(By.xpath("//*[@id='ivs_container']/div/div[2]/div/div[2]/div[2]/div/div/div[1]/div[2]/button")).click();
                                //开始判断是否出出现了弹框
                                isAlertCodeError();
                                if(elemeIspasswordLoingSuccess()){
                                    log.info("验证码登录成功了");
                                    log.info("登录成功");
                                    new WebDriverWait(webDriver, 3).until((WebDriver driver) -> {
                                        JavascriptExecutor js = (JavascriptExecutor) driver;
                                        Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
                                        System.out.println("页面是否已经加载完成"+result);
                                        return result;
                                    });
                                    log.info("开始获取strage信息");
                                    //获取cookie
                                    JavascriptExecutor js = (JavascriptExecutor) webDriver;
                                    String ksid = (String) js.executeScript("return window.localStorage.getItem('ksid')");
                                    String shopId = (String) js.executeScript("return window.localStorage.getItem('shopId')");
                                    String shopName = (String) js.executeScript("return window.localStorage.getItem('shopName')");
                                    log.info("{}{}{}",ksid,shopId,shopName);
                                    storeService.loginByQrCode(ksid,shopId,shopName,userId,username,password);
                                    redisTemplate.opsForValue().set(CODEINFO+userId,new CodeLoginResult("0","验证码登录成功"));

                                }else{
                                    redisTemplate.opsForValue().set(CODEINFO+userId,new CodeLoginResult("500","系统开小差了"));
                                }
                            } catch (Exception e) {
                                CodeLoginResult codeLoginResult = new CodeLoginResult("500", e.getMessage());
                                redisTemplate.opsForValue().set(CODEINFO+userId,codeLoginResult);
                                throw new RuntimeException(e);
                            }finally {
                                webDriver.quit();
                                redisTemplate.delete(userId + "code");
                            }

                        }
                    }).start();

                     return new CodeLoginResult("2","弹出验证码了");
                }
                 throw new BusinessException("未知异常");
            }
        } catch (Exception e) {
            this.webDriver.quit();
            throw e;
        }


    }

    public String getCode(String userId,RedisTemplate redisTemplate)  {
        String code = null;
        redisTemplate.delete(userId + "code");
        long endtime = new Date().getTime() + 1000 * 300;
        while(new Date().getTime() < endtime){
            log.info("正在尝试获取code");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            code = (String) redisTemplate.opsForValue().get(userId + "code");
             if(StringUtils.isNotBlank(code)){
                 log.info("已经获取到code了");
                 break;
             }
        }
        return code;

    }

    //检测是否需要验证码
    public String isCheckVateCode(){
        try {
            WebElement until = new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id='ivs_container']/div/div[2]/div/div[2]/div[2]/div/div/div[1]/div[1]/span/input"))
            );
            return "弹出验证码了";
        }catch (Exception e){
            log.info("没有弹出验证码");
            log.error(e);
            throw new BusinessException(e.getMessage());
        }

    }

    public void isAlertError(){
        try {
            this.webDriver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
            WebElement until = new WebDriverWait(this.webDriver, 1).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[2]/div/div/div/div"))
            );
            if(StringUtils.isNotBlank(until.getText()) && webDriver.getCurrentUrl().equals("https://melody.shop.ele.me/login")){
                throw new BusinessException(until.getText());
            }
        } catch (BusinessException e){
            throw e;
        }catch (Exception e) {
            log.error(e);
        }finally {
            this.webDriver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);
        }
    }

    public void isAlertCodeError(){
        try {
            WebElement until = new WebDriverWait(this.webDriver, 1).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[3]/div/div/div/div"))
            );
            if(StringUtils.isNotBlank(until.getText()) && webDriver.getCurrentUrl().equals("https://melody.shop.ele.me/login")){
                throw new BusinessException(until.getText());
            }
        } catch (BusinessException e){
            throw e;
        }catch (Exception e) {
            log.error(e);
        }
    }
    public void  getQrCodeTest() {
        try {
            this.webDriver.get("https://melody.shop.ele.me/login");
            this.webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[3]/div")).click();
            WebElement element = this.webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div/img"));
            Dimension size = element.getSize();
            Point point = element.getLocation();
            File screenshot = ((TakesScreenshot)this.webDriver).getScreenshotAs(OutputType.FILE);
            BufferedImage fullImg = ImageIO.read(screenshot);
            // 裁剪出元素部分的图片
            Rectangle rect = new Rectangle(point.getX(), point.getY(), size.getWidth(), size.getHeight());
            BufferedImage elementImg = fullImg.getSubimage(rect.x, rect.y, rect.width, rect.height);
            // 保存裁剪后的图片
            ImageIO.write(elementImg, "png", new File("elementScreenshot.png"));

        } catch (Exception e) {
            e.printStackTrace();
            webDriver.quit();
        }
    }

    public static String QRCODEFLAG = "QRCODEFLAG";


    public String  getQrCode(Long userId, UploadService uploadService, IStoreService storeService, RedisTemplate redisTemplate) {
        try {
            this.webDriver.get("https://melody.shop.ele.me/login");
            this.webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[3]/div")).click();
            WebElement element = this.webDriver.findElement(By.xpath("//*[@id=\"app\"]/div/div[2]/div[2]/div/div/div/div[2]/div/img"));
            new WebDriverWait(webDriver, 10).until((WebDriver driver) -> {
                JavascriptExecutor js = (JavascriptExecutor) driver;
                Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
                System.out.println("页面是否已经加载完成"+result);
                return result;
            });
            Dimension size = element.getSize();
            Point point = element.getLocation();
            File screenshot = ((TakesScreenshot)this.webDriver).getScreenshotAs(OutputType.FILE);
            BufferedImage fullImg = ImageIO.read(screenshot);
            // 裁剪出元素部分的图片
            Rectangle rect = new Rectangle(point.getX(), point.getY(), size.getWidth(), size.getHeight());
            BufferedImage elementImg = fullImg.getSubimage(rect.x, rect.y, rect.width, rect.height);
            // 保存裁剪后的图片
            ImageIO.write(elementImg, "png", new File("elementScreenshot.png"));
            String pic = uploadService.upload(convertImageToBinary(elementImg));
            redisTemplate.opsForValue().set(QRCODEFLAG,pic,5,TimeUnit.MINUTES); //二维码五分钟有效
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if(elemeIsLoingSuccess()){
                            log.info("登录后的页面为{}",webDriver.getCurrentUrl());
                            log.info("登录成功了");
                            new WebDriverWait(webDriver, 3).until((WebDriver driver) -> {
                                JavascriptExecutor js = (JavascriptExecutor) driver;
                                Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
                                System.out.println("页面是否已经加载完成"+result);
                                return result;
                            });
                            log.info("开始获取strage信息");
                            //获取cookie
                            JavascriptExecutor js = (JavascriptExecutor) webDriver;
                            String ksid = (String) js.executeScript("return window.localStorage.getItem('ksid')");
                            String shopId = (String) js.executeScript("return window.localStorage.getItem('shopId')");
                            String shopName = (String) js.executeScript("return window.localStorage.getItem('shopName')");
                            storeService.loginByQrCode(ksid,shopId,shopName,userId);

                        }
                    } catch (Exception e) {
                        log.error(e);
                    }finally {
                        redisTemplate.delete(QRCODEFLAG);
                        webDriver.quit();
                    }
                }
            }).start();
            return pic;
        } catch (Exception e) {
            e.printStackTrace();
            redisTemplate.delete(QRCODEFLAG);
            webDriver.quit();
        }
        return null;
    }


    public Boolean elemeIspasswordLoingSuccess() {
        // 自定义一个等待条件，等待元素变得不可见
        ExpectedCondition<Boolean> invisibilityOfElement = new ExpectedCondition<Boolean>() {
            @NullableDecl
            @Override
            public Boolean apply(@NullableDecl WebDriver webDriver) {
                try {
                    boolean result = webDriver.getCurrentUrl().equals("https://melody.shop.ele.me/login");
                    if(result){
                        log.info("还是登录页面,继续等待");
                        return false;
                    }else{
                        return true;
                    }
                } catch (Exception e) {
                    log.error(e);
                    throw new RuntimeException(e);
                }
            }
        };
        Boolean result = null;
        try {
            result = new WebDriverWait(this.webDriver, 3).until(invisibilityOfElement);
            if(!result){
                log.info("元素最终没有消失说明登录没有成功");
            }
            log.info("最终返回结果为如下");
            log.info("最终返回结果为如下{}",webDriver.getCurrentUrl());
            return result;
        } catch (TimeoutException e) {
            log.error(e);
            return false;
        } catch (Exception e){
            log.error(e);
        }
        return false;

    }


    public Boolean elemeIsLoingSuccess() {
        // 自定义一个等待条件，等待元素变得不可见
        ExpectedCondition<Boolean> invisibilityOfElement = new ExpectedCondition<Boolean>() {
            @NullableDecl
            @Override
            public Boolean apply(@NullableDecl WebDriver webDriver) {
                try {
                    boolean result = webDriver.getCurrentUrl().equals("https://melody.shop.ele.me/login");
                    if(result){
                        log.info("还是登录页面,继续等待");
                        return false;
                    }else{
                        return true;
                    }
                } catch (Exception e) {
                    log.error(e);
                    throw new RuntimeException(e);
                }
            }
        };
        Boolean result = null;
        try {
            result = new WebDriverWait(this.webDriver, 300).until(invisibilityOfElement);
            if(!result){
                log.info("元素最终没有消失说明登录没有成功");
            }
            log.info("最终返回结果为如下");
            log.info("最终返回结果为如下{}",webDriver.getCurrentUrl());
            return result;
        } catch (TimeoutException e) {
            log.error(e);
            return false;
        } catch (Exception e){
            log.error(e);
        }
        return false;

    }

    public static byte[] convertImageToBinary(BufferedImage image) throws IOException {
        // 使用ByteArrayOutputStream来写入字节数据
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        // 使用ImageIO.write()方法将BufferedImage写入到输出流中
        ImageIO.write(image, "png", byteArrayOutputStream);

        // 获取字节数组
        byte[] binaryData = byteArrayOutputStream.toByteArray();

        // 关闭输出流（虽然Java会在垃圾回收时自动关闭，但显式关闭是个好习惯）
        byteArrayOutputStream.close();

        // 返回字节数组
        return binaryData;
    }

    public Result loginByCode(String mobile,String code){
        try {
            this.webDriver.get("https://waimaie.meituan.com/new_fe/login_gw#/login");
            this.webDriver.navigate().refresh();
            //点击验证码登录
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[1]/div[2]/div")).click();
            //点击阅读并同意
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/div[4]/div/div/label")).click();
            //输入手机号
            this.webDriver.findElement(By.xpath("//*[@id=\"phone\"]")).sendKeys(mobile);
            //输入验证码
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/div[2]/div/input")).sendKeys(code);
            //点击登录
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/button")).click();

            if(isLoingSuccess()){
                log.info("登录成功");
                return getCookie();
            }else{
                String errMsg = getErrMsg();
                log.error(errMsg);
                throw  new BusinessException(errMsg);
            }
        } catch (Exception e) {
            log.error(e);
            throw e;
        }finally {
            this.webDriver.quit();
        }

    }

    public Boolean sendCode(String mobile){
        try {
            this.webDriver.get("https://waimaie.meituan.com/new_fe/login_gw#/login");
            this.webDriver.navigate().refresh();
            //点击验证码登录
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[1]/div[2]/div")).click();
            //点击阅读并同意
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/div[4]/div/div/label")).click();
            //输入手机号
            this.webDriver.findElement(By.xpath("//*[@id=\"phone\"]")).sendKeys(mobile);
            //点击获取验证码
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/div[2]/div/div")).click();

            if(!isSendSucess()){
                log.info("验证码发送失败，判断是否出现了滑块");
                if(isneedSlider()){
                    log.info("发送失败，可能出现滑块");
                    moveSlider();
                }else{
                    String errMsg = getErrMsg();
                    log.info(errMsg);
                    throw  new BusinessException(errMsg);
                }

                if(!isSendSucess()){
                    throw new BusinessException("未知错误");
                }

            }else{
                log.info("验证码发送成功");
            }
            return true;
        } catch (Exception e) {
            throw e;
        }finally {
            this.webDriver.quit();
        }
    }


    public static  Boolean elemSlider(WebDriver webDriver){
        try {
            WebElement until = new WebDriverWait(webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"baxia-dialog-content\"]"))
            );
            if(!webDriver.getCurrentUrl().contains("login")){
                System.out.println("滑块验证码没有出现可能是出现了vpn警告");
                return false;
            }
            System.out.println("滑块验证码出现了出现了");
            return true;
        } catch (TimeoutException e) {
            System.out.println("滑块验证码没有出现");
            return false;
        }
    }

    @SneakyThrows
    public static  void toSlider(WebDriver webDriver){
        if(elemSlider(webDriver)){
            Actions action = null;
            try {
                Thread.sleep(2000);
                WebElement iframElement = webDriver.findElement(By.xpath("//*[@id=\"baxia-dialog-content\"]"));
                Point location = iframElement.getLocation();
                webDriver.switchTo().frame(iframElement);
                WebElement slider = webDriver.findElement(By.xpath("//*[@id=\"scratch-captcha-btn\"]"));
                Actions actions = new Actions(webDriver);
                action = actions.clickAndHold(slider);
                List<Integer> result = BingTopUtil.splitIntoRandomNumbers(280, 6);
                Actions finalAction = action;
                result.forEach(step->{
                    finalAction.moveByOffset(step,new Random().nextInt(4)).perform();
                });
                WebElement element = webDriver.findElement(By.xpath("//*[@id=\"captcha-answer\"]"));
                Dimension size = element.getSize();
                Point point = element.getLocation();
                File screenshot = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
                BufferedImage fullImg = ImageIO.read(screenshot);
                // 裁剪出元素部分的图片
                Rectangle rect = new Rectangle(location.getX()+point.getX(), location.getY()+point.getY(),  size.getHeight(),size.getWidth());
                BufferedImage elementImg = fullImg.getSubimage(rect.x, rect.y, rect.width, rect.height);
                WebElement titileElement = webDriver.findElement((By.xpath("//*[@id=\"nocaptcha\"]/div[2]/div[1]/div[1]/div/div")));
                Dimension titleSize = titileElement.getSize();
                Point titlePont = titileElement.getLocation();
                //裁剪出提示部分的图片
                Rectangle rect2 = new Rectangle(location.getX()+titlePont.getX(), location.getY()+titlePont.getY(),  titleSize.getHeight(),titleSize.getWidth());
                BufferedImage titleelementImg = fullImg.getSubimage(rect2.x, rect2.y, rect2.width, rect2.height);
                // 保存裁剪后的图片
                ImageIO.write(elementImg, "png", new File("content.png"));
                ImageIO.write(titleelementImg, "png", new File("title.png"));

                // 读取图片base64编码数据
                String captchaData = BingTopUtil.getImageStr("content.png");
                String subCaptchaData = BingTopUtil.getImageStr("title.png");
//        // post图片数据，账号信息，进行打码
                String returnStr = BingTopUtil.sendPost(
                        "http://www.bingtop.com/ocr/upload/",
                        "username=15856902499&password=123456&captchaType=1358&captchaData="+captchaData+"&subCaptchaData="+subCaptchaData,"UTF-8"
                );
                Integer integer = JSON.parseObject(returnStr).getJSONObject("data").getInteger("recognition");
                System.out.println(returnStr);
                int step = integer - 300;

                action.moveByOffset(step,new Random().nextInt(4)).perform();

                Thread.sleep(1000);
                action.release().perform();
                Thread.sleep(1000);

            } catch (Exception e) {
                try {
                    action.release().perform();
                } catch (Exception ex) {
                }
                e.printStackTrace();
            } finally {
                webDriver.switchTo().defaultContent();
            }
            String currentUrl = webDriver.getCurrentUrl();
            System.out.println("浏览器地址为"+currentUrl);
            if(currentUrl.contains("login")){
                Thread.sleep(4000);
                toSlider(webDriver);
            }
        }else{
            System.out.println("滑块已经通过");
        }
    }


    private void isBindPhone(){
        try {
            log.info("开始判断是否需要绑定手机号");
            new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"yodaSubmit\"]"))
            );
            log.info("检测到该账号绑定了手机号");
            throw new BusinessException("绑定了手机号，请使用验证码登录");
        } catch (TimeoutException e) {
            e.printStackTrace();
            log.info("该账号没有绑定手机号");
        }
    }

    private void moveSlider(){
        log.info("开始移动滑块");
        WebElement slider = this.webDriver.findElement(By.xpath("//*[@id=\"yodaBox\"]"));
        Actions actions = new Actions(this.webDriver);
        Actions action = actions.clickAndHold(slider);
//                action.moveByOffset(new Random().nextInt(30)+197,0);
        try {
            int totalstep = 0;
            while(totalstep < 197){
                int step = new Random().nextInt(15)+10;
                totalstep += step;
                action.moveByOffset(step,new Random().nextInt(4)).perform();
            }
            action.release().perform();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        log.info("开始再次判断滑块有没有消失");
        if(isneedSlider()){
            log.info("开始再次判断滑块有没有消失结果没有消失");
            moveSlider();
        }
        log.info("开始再次判断滑块有没有消失结果消失了");
    }

    public Boolean isneedSlider(){
        try {
            Thread.sleep(500);
            new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"yodaBox\"]"))
            );
            log.info("滑块出现了");
            return true;
        } catch (TimeoutException e) {
            log.info("滑块没有出现");
            return false;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private  Boolean isSendSucess() {
        try {
            new WebDriverWait(this.webDriver, 2).until(
                    new ExpectedCondition<WebElement>() {
                        @NullableDecl
                        @Override
                        public WebElement apply(@NullableDecl WebDriver webDriver) {
                            //判断按钮是否变成倒计时
                            WebElement element = webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[2]/div[2]/div/div"));
                            String text = element.getText();
                            if (text.contains("重新获取")) {
                                return element;
                            }
                            return null;
                        }
                    }
            );
            log.info("验证码发送成功");
            return true;
        } catch (TimeoutException e) {
            return false;
        }

    }


    public Result getCookie(){
        new WebDriverWait(this.webDriver, 10).until((WebDriver driver) -> {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
            System.out.println("页面是否已经加载完成"+result);
            return result;
        });
        Set<Cookie> cookies = this.webDriver.manage().getCookies();
        System.out.println(cookies);
        this.webDriver.get("https://waimaieapp.meituan.com/gw/customer/comment/list");
        WebDriverWait wait = new WebDriverWait(this.webDriver, 10);
        wait.until((WebDriver driver) -> {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Boolean result = (Boolean) js.executeScript("return document.readyState === 'complete'");
            System.out.println("页面是否已经加载完成"+result);
            return result;
        });
        Set<Cookie> evCookie = this.webDriver.manage().getCookies();
        System.out.println(evCookie);
        Result result = new Result();
        result.setCode(0);
        CookieInfo cookieInfo = new CookieInfo();
        cookieInfo.setEv_cookie(cookiesToString(evCookie));
        String cookiesstr = cookiesToString(cookies);
        cookieInfo.setCookieStr(cookiesstr);
        if(!cookiesstr.contains("region_id")){
            throw new BusinessException("此账号未开通门店");
        }
        cookieInfo.setCookie(cookieArray(cookies));
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("cookieInfo",cookieInfo);
        result.setData(jsonObject);
        result.setMessage("登录成功");
        System.out.println(JSON.toJSONString(result));
        return result;
    }

    public static String cookiesToString(Set<Cookie> cookies) {
        if (cookies == null || cookies.isEmpty()) {
            return "";
        }

        return cookies.stream()
                .map(cookie ->{
                    return cookie.getName()+"="+cookie.getValue();

                })
                .collect(Collectors.joining("; "));
    }

    public static JSONArray cookieArray(Set<Cookie> cookies) {
        if (cookies == null || cookies.isEmpty()) {
            return null;
        }

        List<JSONObject> collect = cookies.stream()
                .map(cookie -> {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.set("name", cookie.getName());
                    jsonObject.set("value", cookie.getValue());
                    return jsonObject;

                })
                .collect(Collectors.toList());
        JSONArray objects = JSON.parseArray(JSON.toJSONString(collect));
        return objects;
    }
    @Data
    public static class CookieInfo{
        private String cookieStr;
        private String ev_cookie;
        private JSONArray  cookie;
    }
    public Result loginByPassword(String userName, String password){
        try {
            this.webDriver.get("https://waimaie.meituan.com/new_fe/login_gw#/login");
            this.webDriver.navigate().refresh();
            //点击账号登录
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[1]/div[1]/div[1]")).click();
            //点击阅读并同意
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/form/div[4]/div/div/label")).click();
            //收入手机号
            this.webDriver.findElement(By.xpath("//*[@id=\"login\"]")).sendKeys(userName);
            //输入密码
            this.webDriver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(password);
            //点击登录
            this.webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/form/button")).click();

            if(isLoingSuccess()){
                log.info("登录成功");
                return getCookie();
            }else{
                if(isneedSlider()){
                    log.info("发送失败，可能出现滑块");
                    moveSlider();
                }
                String errMsg = getErrMsg();
                if(StringUtils.isBlank(errMsg)){
                    isBindPhone();
                }
                if(isLoingSuccess()){
                    log.info("登录成功");
                    return getCookie();
                }
                log.info(errMsg);
                throw new BusinessException(errMsg);
            }
        } catch (Exception e) {

            throw e;
        }finally {

            this.webDriver.quit();
        }
    }

    public Boolean isLoingSuccess() {
        // 自定义一个等待条件，等待元素变得不可见
        ExpectedCondition<Boolean> invisibilityOfElement = new ExpectedCondition<Boolean>() {
            @NullableDecl
            @Override
            public Boolean apply(@NullableDecl WebDriver webDriver) {
                try {
                    WebElement el = webDriver.findElement(By.xpath("//*[@id=\"epLoginComponent\"]/div[1]/div[1]/div[1]"));
                    boolean result = !el.isDisplayed();
                    return result;
                } catch (org.openqa.selenium.NoSuchElementException e) {
                    // 如果
                    log.info("元素从DOM中消失了，也视为不可见");
                    return true;
                }
            }
        };
        Boolean result = null;
        try {
            result = new WebDriverWait(this.webDriver, 4).until(invisibilityOfElement);
            if(!result){
                log.info("元素最终没有消失说明登录没有成功");
            }
            return result;
        } catch (TimeoutException e) {
            return false;
        }

    }

    public  String getErrMsg(){
        try {
            log.info("开始判断有没有弹出错误信息");
            WebElement until = new WebDriverWait(this.webDriver, 2).until(
                    ExpectedConditions.visibilityOfElementLocated(By.className("ep-message_content"))
            );
            log.info("弹出了错误信息");
            return until.getText();
        } catch (TimeoutException e) {
            log.info("没有弹出错误信息");
            return null;
        }


    }





}
